package com.quest.space.handler;

import com.intellij.completion.ngram.slp.util.Pair;
import com.intellij.openapi.ui.Messages;
import com.quest.space.MainWindow;
import com.quest.space.data.*;
import com.quest.space.poker.base.bean.QuestException;
import com.quest.space.poker.base.enums.PokerTypeEnum;
import com.quest.space.poker.base.enums.TopicEnum;
import com.quest.space.poker.dto.PokerDto;
import com.quest.space.poker.dto.TableDto;
import com.quest.space.utils.PokerClientUtil;
import com.quest.space.websocket.StompClient;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.quest.space.handler.EventHandler.handleRobotPoker;

public class PokerHandler {
    private static final String player1 = "1";
    private static final String player2 = "2";
    private static final String robotName = "【farmer】 \n";
    private static final String destination = "/app/server";


    public static void handle(TableDto table) {
        MainContext context = MainWindow.mainContext;
        String error = table.getError();
        if (StringUtils.isNotEmpty(error)) {
            Messages.showInfoMessage(error, "输入有误");
            context.getTextArea4().setText("");
            return;
        }
        Map<String, String> pokers = table.getShowPokers();
        String userId = UserCache.userId;
        UserCache.gameId = table.getTableId();
        context.getTextArea3().setText(table.getPokers().get(userId).stream().map(PokerDto::getName).collect(Collectors.joining()));
        String msg1 = robotName;
        String msg2 = robotName;
        if (pokers != null) {
            msg1 += pokers.get(player1);
            msg2 += pokers.get(player2);
        }
        context.getTextArea1().setText(msg1);
        context.getTextArea2().setText(msg2);
        if (table.isOver()) {
            String msg = "Game is over";
            msg += userId.equals(table.getWinner()) ? "You won" : " You lost";
            context.getSysArea().setText(msg);
            context.getButton1().setText("continue");
            context.getButton3().setVisible(false);
            context.getTextArea3().setEditable(true);
        } else {
            String content = context.getSysArea().getText();
            Map<String, String> showMap = table.getShowPokers();
            if (showMap != null && table.getShowPlayer() != null) {
                String showStr = showMap.get(table.getShowPlayer());
                if (!"pass".equals(showStr)) {
                    content += showStr;
                    context.getSysArea().setText(content);
                }
            }
        }
    }

    public static void handlePoker() {
        MainContext context = MainWindow.mainContext;
        String submitText = context.getButton1().getText();
        if ("submit".equals(submitText)) {
            sendToServer(context.getTextArea4().getText());
        } else if ("continue".equals(submitText)) {
            handleRobotPoker();
        }
    }

    public static void sendToServer(String data) {
        data = data.replace(" ", "");
        checkPoker(data);
        MainContext context = MainWindow.mainContext;
        WebSocketMsg msg = new WebSocketMsg();
        msg.setTopic(TopicEnum.POKER.getTitle());
        msg.setFrom(UserCache.userId);
        msg.setTableId(UserCache.gameId);
        msg.setData(data);
        StompClient.sendMessage(destination, msg);
        context.getTextArea4().setText("");
    }

    private static void checkPoker(String poker) {
        if ("pass".equals(poker)) {
            return;
        }
        String playerId = UserCache.userId;
        TableDto table = UserCache.table;
        List<PokerDto> pokerList = PokerClientUtil.sortPokerStr(poker);
        List<PokerDto> allPokers = table.getAllPokers(playerId);
        //遍历输入的牌是否存在于原始牌中
        Pair<Boolean, String> pair = exist(pokerList, allPokers);
        if (!pair.left) {
            Messages.showInfoMessage("输入牌型【"+ pair.right +"】不存在", "ERROR");
            throw new QuestException();
        }
        //获取牌型
        PokerTypeEnum pokerType = PokerTypeEnum.getPokerType(poker);
        if (pokerType == null) {
            Messages.showInfoMessage("输入牌型【"+ poker +"】不符合规则", "ERROR");
            throw new QuestException();
        }
        String prePoker = table.getPrePoker();
        List<PokerDto> prePokerList = table.getPrePokerList();
        PokerTypeEnum prePokerType = table.getPrePokerType();
        //当前牌桌为第一次出牌或者上一手出牌人为自己时，不需要判断当前牌，直接出
        boolean check = !StringUtils.isEmpty(prePoker);
        if (playerId.equals(table.getPrePlayer())) {
            check = false;
        }
        //比较与上一手牌型的大小
        if (check) {
            //先比较牌型是否一致
            if (!comparePokerType(pokerType, prePokerType)) {
                Messages.showInfoMessage("牌型不符合规则", "ERROR");
                throw new QuestException();
            }
            //再比较大小，比较总值大小
            if (!comparePokerValue(poker, prePoker, pokerList, prePokerList, pokerType)) {
                Messages.showInfoMessage("大小不符合规则", "ERROR");
                throw new QuestException();
            }
        }
    }

    private static boolean comparePokerType(PokerTypeEnum current, PokerTypeEnum old) {
        //先判断当前牌是否为炸弹
        if (current.equals(PokerTypeEnum.BOMB)) {
            return true;
        } else {
            return current.equals(old);
        }
    }

    private static boolean comparePokerValue(String poker, String oldPoker, List<PokerDto> currentList, List<PokerDto> oldList, PokerTypeEnum pokerType) {
        if (poker.equals("wW")) {//王炸直接返回
            return true;
        }
        return PokerClientUtil.compare(currentList, oldList, poker, oldPoker, pokerType);
    }

    private static Pair<Boolean, String> exist(List<PokerDto> pokers, List<PokerDto> all) {
        for (PokerDto poker : pokers) {
            boolean exist = false;
            for (PokerDto a : all) {
                if (!a.getDelete() && poker.getName().equals(a.getName())) {
                    a.setDelete(true);
                    exist = true;
                    break;
                }
            }
            all.forEach(a -> a.setDelete(false));
            if (!exist) {
                return new Pair<>(false, poker.getName());
            }
        }
        return new Pair<>(true, "");
    }


}

